// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// w [author] rhyme_lph
// d [email]  rhymelph@gmail.com
// e [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:dio/src/response.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/account_entity.dart';
import 'package:finance_app/src/entities/payment_entity.dart';
import 'package:finance_app/src/entities/transaction_entity.dart';
import 'package:finance_app/src/http_service/http_account_service.dart';
import 'package:finance_app/src/http_service/http_payment_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/mixin/filter_payment_sort_mixin.dart';
import 'package:finance_app/src/mixin/format_group_map_mixin.dart';
import 'package:finance_app/src/mixin/refresh_mixin.dart';
import 'package:finance_app/src/mixin/scroll_to_hide_mixin.dart';
import 'package:finance_app/src/mixin/search_data_list_mixin.dart';
import 'package:finance_app/src/mixin/time_sort_mixin.dart';
import 'package:finance_app/src/provider/dashboard/bank/cash_and_bank_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/widgets/bottom_sheet/dashboard_add_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';

class AllPaymentProvider extends BaseProvider<List<PaymentEntity>>
    with
        TimeSortMixin,
        SearchDataListMixin,
        RefreshMixin<List<PaymentEntity>, List<PaymentEntity>>,
        FormatGroupMapLocalMixin<PaymentEntity>,
        FilterPaymentSortMixin,
        ScrollToHideMixin,
        CheckPlanMixin {
  int accountId;

  @override
  Future get dataFuture => HttpPaymentService.paymentList(
      startDate: startTime,
      endDate: endTime,
      accountId: accountId?.toString() ??
          currentSelectFilterAccount.map((e) => e.id).join(','));

  @override
  Future<void> onRefresh() async {
    await post(dataFuture, autoHandler: AutoHandler.Toast, onSuccess: (result) {
      data = transformData(
          getEntityFromResult<List<PaymentEntity>>(result), false);
      update();
    });
    refreshController.refreshCompleted();
  }

  @override
  void unFocus() {}

  @override
  void searchRefreshData(searchData) {
    transformData(data, false);
    update();
  }

  @override
  List<PaymentEntity> get dataList => data;

  @override
  List<PaymentEntity> getFromRequestResult(
      Response<dynamic> result, bool isRefresh) {
    if (isRefresh) {
      groupMap.clear();
    }
    List<PaymentEntity> paymentList =
        getEntityFromResult<List<PaymentEntity>>(result);
    contactToMap(paymentList);
    return paymentList;
  }

  @override
  Future get refreshFuture => dataFuture;

  void contactToMap(List<PaymentEntity> list) {
    sortGroupToMap(
      list,
      sort: (b, a) => sortIssuesAt(a, b, (t) => t.issuedAt, (t) => t.id),
      filter: (a) {
        if (onFilterSearch(searchController.text, a.name)) {
          if (currentSelectFilterList.length > 0) {
            if (currentSelectFilterList.firstWhere((element) {
                  if (a.type == 'transfer') {
                    return element == 'Account Transfer';
                  } else {
                    return mapToKey[element] == a.flowType;
                  }
                }, orElse: () => null) !=
                null) {
              return true;
            } else {
              return false;
            }
          } else {
            return true;
          }
        } else {
          return false;
        }
      },
      group: (a) => groupMonth(a, (t) => a.issuedAt),
    );
  }

  void onNavPayment(PaymentEntity e) async {
    var result;
    if (e.type == 'transfer') {
      result = await Routes.navigateTo(
          RouterGenProviders.newAccountTransferPage,
          params: {
            'data': e,
          });
    } else if (e.flowType == 'out') {
      result = await Routes.navigateTo(RouterGenProviders.newCashOutPage,
          params: {'paymentData': e, 'isSelectMode': true});
    } else if (e.flowType == 'in') {
      result = await Routes.navigateTo(RouterGenProviders.newCashInPage,
          params: {'paymentData': e, 'isSelectMode': true});
    }
    if (result != null && result is PaymentEntity) {
      e.fromJson(e.toJson());
      update();
    } else if ((result != null && result == true) ||
        (result is Map && result['delete'] == true)) {
      data.remove(e);
      transformData(data, false);
      update();
    }
  }

  @override
  FutureOr<List<PaymentEntity>> transformData(
      List<PaymentEntity> d, bool isCache) {
    groupMap.clear();
    contactToMap(d);
    return super.transformData(d, isCache);
  }

  void onNavAdd() {
    if (isPlanExpired()) return;
    obtainContext?.call((context) async {
      await showDashboardAddBottomSheet(context,
          dashTypes: [DashBoardAddType.accountTransaction]);
      refreshController.requestRefresh();
    });
  }

  @override
  void initState() {
    super.initState();
    allAccounts = Providers.get<CashAndBankProvider>(
            RouterGenProviders.cashAndBankPage, null)
        .data;
  }
}
